package cn.gongxi.weibo.common.exception;

import cn.gongxi.weibo.common.response.JsonResult;
import cn.gongxi.weibo.common.response.StatusCode;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

/**
 * 全局异常处理器
 * @ControllerAdvice 注解
 * 将此类标识为全局异常处理器，处理由控制器抛出的异常
 * 如果控制器抛出异常之后，框架会检查是否有全局异常处理器可以处理该异常，
 *       如果有，则调用全局异常处理器进行处理
 *       如果没有，则SpringMVC会抛出异常，由SpringMVC的默认异常处理器进行处理
 *
* @ExceptionHandler 注解
 * 将此注解标识的方法，标识为全局异常处理方法
 *
 * @RestControllerAdvice
 * 组合注解
 * @ControllerAdvice
 * @ResponseBody
 *
 * 控制器异常处理顺序：
 * 1、定位全局异常处理器
 * 2、调用对应的异常处理方法进行处理
 * 3、调用该异常父类异常的处理方法进行处理
 *4、最后由能处理所有异常的异常处理方法进行处理  Throwable
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /*
    * 异常处理方法：IllegalArgumentException
     */
    @ExceptionHandler
//    @ResponseBody
    public JsonResult doHandleIllegalArgumentException(IllegalArgumentException ex){
        // 在终端输出异常信息
        log.error("IllegalArgumentException" + ex.getMessage());
        return JsonResult.fail(ex.getMessage());
    }
    /*
    * 异常处理方法：ConstraintViolationException
     */
    @ExceptionHandler
    public JsonResult doHandleConstraintViolationException(ConstraintViolationException ex){
        // 在终端输出异常信息
        log.error("ConstraintViolationException" + ex.getMessage());
        String data = ex.getMessage();
        if(data.contains(":")){
            String error = data.split(":")[1].trim();
            // 获取id
            String id = data.split(":")[0].substring(data.indexOf(".")+1);
            log.error(id);
            data = id + ":" + error;
        }
        return new JsonResult(StatusCode.VALIDATED_ERROR,data);
    }

    /*
    * 异常处理方法：RuntimeException
     */
    @ExceptionHandler
    public JsonResult doHandleRuntimeException(RuntimeException ex){
        // 在终端输出异常信息
        log.error("RuntimeException" + ex.getMessage());
        return JsonResult.fail(ex.getMessage());
    }

    /**
     * 异常处理方法：Validation校验POJO类型的数据的合法性
     *
     */
    @ExceptionHandler
    public JsonResult doHandleMethodArgumentNotValidException(MethodArgumentNotValidException ex){
        // 在终端输出异常信息,获取数据校验异常信息
        log.error("MethodArgumentNotValidException" + ex.getMessage());
        String data = ex.getFieldError().getDefaultMessage();
        return new JsonResult(StatusCode.VALIDATED_ERROR,data);
    }

    // 当所有的方法都没有处理时，会调用下面方法进行处理
   /* @ExceptionHandler
    public JsonResult doThrowable(Throwable ex){
        log.error("Throwable" + ex.getMessage());
        return new JsonResult(StatusCode.THROWABLE_ERROR,ex.getMessage());
    }*/
}
